/**
 * @(#)DownLoadMonitorServiceImpl.java 2017年3月1日
 * Copyright(C) 2017 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.monitor.service;


import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.jsbd.boss.common.monitor.MonitorContentTemplate;
import org.jsbd.boss.dao.impl.SimulatorActionLogDAOImpl;
import org.jsbd.boss.domian.channel.ChannelApkConfig;
import org.jsbd.boss.domian.monitor.MonitorDownloadInfo;
import org.jsbd.boss.domian.monitor.MonitorDownloadTotal;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * 流量下载统计类
 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
 * @version 1.0.0
 */
@Service("monitorDownLoadService")
public class MonitorDownLoadServiceImpl extends MonitorBaseService{
	public static final Logger LOGGER = LoggerFactory.getLogger(MonitorDownLoadServiceImpl.class);

	protected static final DecimalFormat RATE_FORMAT = new DecimalFormat("#0.00");
	
	@Autowired
	private SimulatorActionLogDAOImpl simulatorActionLogDao;

	@Override
	public Map<String, String> getMonitorContent(List<ChannelApkConfig> apkList,
			Map<String, ChannelApkConfig> apkConfigMap, Map<String, Object> conditionMap) {
		
		Map<String, String> resultMap=null;
		try{
			//从数据库获取记录
			List<MonitorDownloadInfo> recordList=simulatorActionLogDao.getSimulatorActionDownloadLogList(conditionMap);
			
			if(recordList==null||recordList.isEmpty()){
				return new HashMap<String,String>();
			}
			
			//处理从数据库获取的数据
			resultMap=handlerData(recordList,apkConfigMap);
		}catch(Exception e){
			LOGGER.error("",e);
			resultMap=productExceptionMap(e,"流量监控");
		}
		
		return resultMap;
	}
	
	/**
	 * 
	 * 处理从数据库获取来的数据
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param recordList
	 * @return
	 */
	public Map<String,String> handlerData(List<MonitorDownloadInfo> recordList,Map<String, ChannelApkConfig> apkConfigMap){
		SimpleDateFormat minuteDf=new SimpleDateFormat("yyyy-MM-dd HH:mm");
		SimpleDateFormat tenSecondDf=new SimpleDateFormat("yyyy-MM-dd HH:mm:s");
		
		//按5个纬度进行统计：按1分钟，按10秒，按mark,按每分钟mark,按每10秒mark
		Map<String,Double> markMap=new HashMap<String,Double>();
		Map<String,Double> miniteMap=new HashMap<String,Double>();
		Map<String,Double> secondMap=new HashMap<String,Double>();
		Map<String,Double> miniteMarkMap=new HashMap<String,Double>();
		Map<String,Double> secondMarkMap=new HashMap<String,Double>();
		
		for(MonitorDownloadInfo record:recordList){
			String mark=record.getMark();
			String mimuteDate=minuteDf.format(record.getCreateTime());
			String secondDate=tenSecondDf.format(record.getCreateTime());
			
			JSONObject dataJson=JSON.parseObject(record.getMsg());
			Long fileSize=Long.valueOf(dataJson.getString("fileSize"));
			
			addNum(miniteMap,mimuteDate,fileSize);
			addNum(secondMap,secondDate,fileSize);
			addNum(markMap,mark,fileSize);
			addNum(miniteMarkMap,mimuteDate+"_"+mark,fileSize);
			addNum(secondMarkMap,secondDate+"_"+mark,fileSize);
		}
		
		//获取按分钟统计的列表
		List<MonitorDownloadInfo> minuteList=getDownloadList(miniteMap,null);
		//获取按10秒统计的列表
		List<MonitorDownloadInfo> secondList=getDownloadList(secondMap,null);
		//获取按mark统计的列表
		List<MonitorDownloadInfo> markList=getDownloadList(markMap,apkConfigMap);
		//获取按峰值统计的列表
		List<MonitorDownloadTotal> totalList=getTotalList(minuteList.get(0),
				secondList.get(0),getMarkMaxSizeFromMap(miniteMarkMap),
				getMarkMaxSizeFromMap(secondMarkMap),apkConfigMap);
		
		//生成邮件附件
		String attachment=productEmailAttachment(MonitorContentTemplate.FLOW_TOTAL_HEADER,"FLOW_MONITOR",
				totalList,minuteList,secondList,markList);
		
		//生产邮件内容
		String emailContent=productEmailContent(totalList,MonitorContentTemplate.FLOW_TOTAL_HEADER);
		
		Map<String,String> resultMap=new HashMap<String,String>();
		resultMap.put("content", emailContent);
		resultMap.put("attachFile", attachment);
		resultMap.put("sheetName","流量监控");
		return resultMap;
	}
	
	/**
	 * 
	 * 获取按峰值统计的列表
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param minuteMaxInfo  按分钟获取的最大流量记录
	 * @param secondMaxInfo  按10秒获取的最大流量记录
	 * @param minuteMarkMaxInfo  按分钟获取使用流量最多的mark
	 * @param secondMarkMaxInfo  按10秒获取使用流量最多的mark
	 * @return
	 */
	private List<MonitorDownloadTotal> getTotalList(MonitorDownloadInfo minuteMaxInfo,
			MonitorDownloadInfo secondMaxInfo,MonitorDownloadInfo minuteMarkMaxInfo,
			MonitorDownloadInfo secondMarkMaxInfo,Map<String, ChannelApkConfig> apkConfigMap){
		
        List<MonitorDownloadTotal> totalList=new ArrayList<MonitorDownloadTotal>();
		
		MonitorDownloadTotal minute=new MonitorDownloadTotal();
		minute.setName("1分钟最大流量");
		minute.setItemKey("flow_minute");
		minute.setFlowSize(minuteMaxInfo.getDownloadSize());
		minute.setKey(minuteMaxInfo.getKey());
		
		MonitorDownloadTotal second=new MonitorDownloadTotal();
		second.setName("10秒最大流量");
		second.setItemKey("flow_second");
		second.setFlowSize(secondMaxInfo.getDownloadSize());
		second.setKey(secondMaxInfo.getKey());
		
		MonitorDownloadTotal minuteMark=new MonitorDownloadTotal();
		minuteMark.setName("1分钟内流量最大mark");
		minuteMark.setItemKey("flow_minute_mark");
		minuteMark.setFlowSize(minuteMarkMaxInfo.getDownloadSize());
		minuteMark.setKey(getApkName(apkConfigMap,minuteMarkMaxInfo.getKey()));
		
		MonitorDownloadTotal secondMark=new MonitorDownloadTotal();
		secondMark.setName("10秒内流量最大mark");
		secondMark.setItemKey("flow_second_mark");
		secondMark.setFlowSize(secondMarkMaxInfo.getDownloadSize());
		secondMark.setKey(getApkName(apkConfigMap,secondMarkMaxInfo.getKey()));
		
		totalList.add(minute);
		totalList.add(second);
		totalList.add(minuteMark);
		totalList.add(secondMark);
		
		vailidateOk(totalList);
		return totalList;
	}
	
	/**
	 * 对流量进行校验
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param totalList
	 */
	private void vailidateOk(List<MonitorDownloadTotal> totalList){
		Map<String,String> configMap=getMonitorConfig();
		for(MonitorDownloadTotal downloadInfo:totalList){
			String itemValue=configMap.get(downloadInfo.getItemKey());
			if(StringUtils.isBlank(itemValue)){
				continue;
			}
			if(downloadInfo.getFlowSize()>Double.valueOf(itemValue)){
				downloadInfo.setRed();
			}
		}
	}
	
	/**
	 * 
	 * 累加数据保存到一个map
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param dataMap
	 * @param key
	 * @param num
	 */
	private void addNum(Map<String,Double> dataMap,String key,Long num){
		Double size=dataMap.get(key);
		if(size==null){
			size=0D;
		}
		if(num==null){
			num=0L;
		}
		//按兆(MB)输出
		size=size+num*1.0/1000/1000;
		dataMap.put(key,size);
	}
	
	
	/**
	 * 
	 * 按流量倒序获取列表数据
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param dataMap
	 * @return
	 */
	private List<MonitorDownloadInfo> getDownloadList(Map<String,Double> dataMap,Map<String, ChannelApkConfig> apkConfigMap){
		List<MonitorDownloadInfo> downloadList=new ArrayList<MonitorDownloadInfo>(dataMap.size());
		for(Entry<String, Double> entity:dataMap.entrySet()){
			MonitorDownloadInfo info=new MonitorDownloadInfo();
			info.setDownloadSize(entity.getValue());
			info.setKey(getApkName(apkConfigMap,entity.getKey()));
			downloadList.add(info);
		}
		Collections.sort(downloadList, new DownloadComparator());
		return downloadList;
	}
	
	private String getApkName(Map<String, ChannelApkConfig> apkConfigMap,String key){
		if(apkConfigMap==null){
			return key;
		}
		
		ChannelApkConfig config=apkConfigMap.get(key);
		if(config==null){
			return key;
		}
		
		if(StringUtils.isNotBlank(config.getApkName())){
			key=config.getApkName();
		}
		return key;
	}
	
	/**
	 * 
	 * 按流量获取最大值
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param dataMap
	 * @return
	 */
	private MonitorDownloadInfo getMarkMaxSizeFromMap(Map<String,Double> dataMap){
		MonitorDownloadInfo record=new MonitorDownloadInfo();
		record.setDownloadSize(0D);
		for(Entry<String, Double> entity:dataMap.entrySet()){
			if(entity.getValue()-record.getDownloadSize()>0){
				String key=entity.getKey();
				record.setDownloadSize(entity.getValue());
				int index=key.indexOf("_");
				if(index>0){
					key=key.substring(index+1);
				}
				record.setKey(key);
			}
		}
		
		return record;
	}
	
	
	/**
	 * 
	 * 比较器
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @version 1.0.0
	 */
	static class DownloadComparator implements Comparator<MonitorDownloadInfo> {
	    @Override
		public int compare(MonitorDownloadInfo arg0, MonitorDownloadInfo arg1) {
	    	if(arg1.getDownloadSize().equals(arg0.getDownloadSize())){
	    		return 0;
	    	}
	    	if(arg1.getDownloadSize()-arg0.getDownloadSize()>0){
	    		return 1;
	    	}else{
	    		return -1;
	    	}
		}
	}

}
